package com.chester.springbootseventeen.config.rabbit;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @author chester7cheng
 */
@Configuration
@Slf4j
public class RabbitConfig {

    public static final String DIRECT_EXCHANGE = "direct-exchange-chester";
    public static final String TOPIC_EXCHANGE = "topic-exchange-chester";
    public static final String FANOUT_EXCHANGE = "fanout-exchange-chester";
    public static final String HEADERS_EXCHANGE = "headers-exchange-chester";
    public static final String CUSTOMER_EXCHANGE = "customer-exchange-chester";
    public static final String DELAY_EXCHANGE = "delay-exchange-chester";
    public static final String DEAD_LETTER_EXCHANGE = "dead-letter-exchange-chester";

    public static final String TOPIC_ROUTING_KEY = "com.chester.#";
    public static final String ROUTING_KEY= "com.chester.seventeen.rabbitmq";
    public static final String DELAY_ROUTING_KEY = "com.chester.seventeen.delay";
    public static final String DEAD_LETTER_ROUTING_KEY = "com.chester.seventeen.deadletter";

    public static final String DEFAULT_QUEUE = "default-queue-chester";
    public static final String TOPIC_QUEUE = "manual-queue-chester";
    public static final String FANOUT_QUEUE = "fanout-queue-chester";
    public static final String HEADERS_QUEUE = "headers-queue-chester";
    public static final String DELAY_QUEUE = "delay-queue-chester";
    public static final String DEAD_LETTER_QUEUE = "dead-letter-queue-chester";

    @Bean
    public Queue defaultQueue(){
        return new Queue(DEFAULT_QUEUE, true);
    }

    @Bean
    public DirectExchange deadLetterExchange(){
        return new DirectExchange(DEAD_LETTER_EXCHANGE);
    }
    @Bean
    public Queue deadLetterQueue(){
        return new Queue(DEAD_LETTER_QUEUE, true);
    }
    @Bean
    public Binding deadLetterBinding(Queue deadLetterQueue, DirectExchange deadLetterExchange){
        return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with(DEAD_LETTER_ROUTING_KEY);
    }



    @Bean
    public DirectExchange delayExhchange(){
        return new DirectExchange(DELAY_EXCHANGE);
    }
    @Bean
    public Queue delayQueue(){
        Map<String, Object> params = new HashMap<>(2);
        //对队列中消息的条数进行限制  x-max-length
        //对队列中消息的总量进行限制  x-max-length-bytes
//        params.put("x-max-length", 7);
        //x-dead-letter-exchange 声明了队列里的死信转发到的DLX名称
        params.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
        // x-dead-letter-routing-key 声明了这些死信在转发时携带的 routing-key 名称
        params.put("x-dead-letter-routing-key", DEAD_LETTER_ROUTING_KEY);
        return new Queue(DELAY_QUEUE, true, false, false, params);
    }
    @Bean
    public Binding delayBinding(Queue delayQueue, DirectExchange delayExhchange){
        return BindingBuilder.bind(delayQueue).to(delayExhchange).with(DELAY_ROUTING_KEY);
    }

    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(TOPIC_EXCHANGE);
    }
    @Bean
    public Queue topicQueue(){
        return new Queue(TOPIC_QUEUE, true);
    }
    @Bean
    public Binding topicBinding(Queue topicQueue, TopicExchange topicExchange){
        return BindingBuilder.bind(topicQueue).to(topicExchange).with(TOPIC_ROUTING_KEY);
    }

    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange(FANOUT_EXCHANGE);
    }
    @Bean
    public Queue fanoutQueue(){
        return new Queue(FANOUT_QUEUE, true);
    }
    @Bean
    public Binding fanoutBinding(Queue fanoutQueue, FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue).to(fanoutExchange);
    }

    @Bean
    public HeadersExchange headersExchange(){
        return new HeadersExchange(HEADERS_EXCHANGE);
    }
    @Bean
    public Queue headersQueue(){
        return new Queue(HEADERS_QUEUE, true);
    }
    @Bean
    public Binding headersBinding(Queue headersQueue, HeadersExchange headersExchange){
        Map<String, Object> map = new HashMap<>(2);
        map.put("First", "A");
        map.put("Fourth", "D");
        return BindingBuilder.bind(headersQueue).to(headersExchange).whereAny(map).match();
    }

    @Bean
    public RabbitTemplate rabbitTemplate(CachingConnectionFactory connectionFactory){
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setPublisherReturns(true);
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> log.info("消息发送成功：correlationData({}),ack({}),cause({})", correlationData, ack, cause));
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> log.info("消失丢失：message({}),replyCode({}),replyText({}),exchange({}),routingKey({})", message, replyCode, replyText, exchange, routingKey));
        rabbitTemplate.setRecoveryCallback(context -> {
            try {
                log.info("消息recovery:({})", JSON.toJSONString(context));
            }catch (Exception ex) {
                ex.printStackTrace();
            }
            return context;
        });

        return rabbitTemplate;
    }






}
